To figure this out I actually installed the Markdown pack then recreated what you did.
In reading the documentation for for the Markdown pack at GitHub it demonstrates two different predicates,
md_parse_string/2 which was in your question and
md_html_string/2 which was not in your question.
Upon trying this and seeing that
?- md_html_string("# Hello #",Html).
Html = "\n\n<h1>Hello</h1>\n\n".
generates valid HTML and
?- md_parse:md_parse_string("Hi", Blocks).
Blocks = [p([\["Hi"]])].
generates a list ready for use with html//1 it became much clearer.
If all you want to do is create Markdown from an input string then use
If you need to create markdown that will be embedded with other input to html//1 to create some html then use md_parse_string/2.
Since md_parse_string/2 created a list ready for html//1 the understanding of the
\ is learned by reading the documentation for html//1 which notes
Escape sequence to add atoms directly to the output list. This can be used to embed external HTML code or emit script output. List is a list of the following terms:
Fmt - Args
Fmt and Args are used as format-specification and argument list to format/3. The result is added to the output list.
Atomic values are added directly to the output list.
However that is different from
Invoke the non-terminal Term in the calling module. This is the common mechanism to realise abstraction and modularisation in generating HTML.
which is noted in this question
What is this? \css and \js Something with library(http/http_server)?
In checking the GitHub documentation for the pack Markdown, there are references to html/1 which is not a standard SWI-Prolog predicate. However html//1 is a standard SWI-Prolog library predicate.