Why I can't use the same code from Drupal 7 in Drupal 8 to generate a button with FAPI?
The reason why it is not working in Drupal 8 as in Drupal 7 is, that prefix and suffix are passed to xssFilterAdminIfUnsafe() function in doRender() function. Thus preventing all tags except the tags specified in $adminTags.

Excerpt from doRender:

  // We store the resulting output in $elements['#markup'], to be consistent
  // with how render cached output gets stored. This ensures that placeholder
  // replacement logic gets the same data to work with, no matter if #cache is
  // disabled, #cache is enabled, there is a cache hit or miss.
  $prefix = isset($elements['#prefix']) ? $this-&gt;xssFilterAdminIfUnsafe($elements['#prefix']) : '';
  $suffix = isset($elements['#suffix']) ? $this-&gt;xssFilterAdminIfUnsafe($elements['#suffix']) : '';

  $elements['#markup'] = Markup::create($prefix . $elements['#children'] . $suffix);


You can use '#allowed_tags' property to enable specific tags. So this should work:

  $form['submit'] = array(
  '#type' =&gt; 'markup',
  '#markup' =&gt; "&lt;button type ='submit'&gt;&lt;span&gt;" . t('Login') . "&lt;/span&gt;&lt;/button&gt;",
  '#allowed_tags' =&gt; ['button', 'span'],  
  );


But '#allowed_tags' property will not work for '#prefix' and '#suffix'.