What’s a safe / good way to output HTML safely within WordPress templates?

It depends on the context. In a template you’d just echo it:

<div>
    <?php echo parse_html_for_images(); ?>
</div>

In a function you might want to concatenate it with something else:

function wpse_303376_thumbnail() {
    return '<div>' . parse_html_for_images() . '</div>';
}

In a shortcode callback with lots other markup you might want to use output buffering, since shortcodes require you return the entire output:

function wpse_303376_shortcode() {
    ob_start();

    echo '<div>';
    echo parse_html_for_images();
    echo '</div>';

    return ob_get_clean();
}

Escaping is an entirely separate issue, and is about ensuring unsafe data, like user input, can’t do anything malicious or break your markup. For example, you might want to escape the thumbnail URL in your function to ensure it’s a URL and not a script tag:

function parse_html_for_images() {
    return '<img src="' . esc_url( thumbnail_url() ) . '">';
}

But there’s no point escaping HTML that you have hard-coded into the template or function, since it’s predictable.