Should a cache tag only render array for an otherwise empty block work?
You are right about this, you need content (in form of a render element) for the cache metadata to be recognized. But you don't need to worry about this, because BlockViewBuilder detects an empty block and adds a markup render element with an empty string:

public static function preRender($build) {
    ...
    if ($content !== NULL &amp;&amp; !Element::isEmpty($content)) {
      ...
    }
    else {
      // Abort rendering: render as the empty string and ensure this block is
      // render cached, so we can avoid the work of having to repeatedly
      // determine whether the block is empty. For instance, modifying or adding
      // entities could cause the block to no longer be empty.
      $build = [
        '#markup' =&gt; '',
        '#cache' =&gt; $build['#cache'],
      ];
      ...