`root` could work as a regular function. I just double checked by converting it in tidewave.ai and it worked just fine! And I believe this is true since Phoenix v1.6 (or v1.7?) when we unified everything to be function components.
So let’s answer this by parts.
First, why do we need layouts?
Mainly because LiveView pages need to denote some content that cannot be live updated. This is typically in the `head` tag. We know there are frameworks who have attempted to update and merge `head` tags but it is very easy to run into hard-to-debug JavaScript bugs and corner-cases in browser. So the root layout helps us denote the static part.
Who renders the layout? After all, we could have made it so all of your regular templates simply called `<Layout.root>`.
Per the above, we know that the contents of `<Layout.root>` cannot be updated and therefore they should not be re-rendered. If we made your template call it, the one rendered on every LiveVIew update, then we would always re-render the root layout too, only to later figure out a way to discard its updates, which would be wasteful.
Beyond the above, it is important to note that frameworks generally want to own how the layout is rendered because it can lead to UX improvements such as sending the layout upfront, up to the `body` tag, before your LiveView and Controllers get invoked. This would allow browsers to parse `head` tag while you are still runing queries and what not, leading to faster page loads. Of course, there are complications, such as what to do if you send the `head` and then you get an exception, but the point is that leaving the framework to control how the layout is rendered can be feature!
IMO, this is not about inheritance at all, especially because frameworks that do offer template inheritance allow you to extend the layout with additional information beyond the inner block, which we don’t. We intentionally keep the layout decoupled from the application contents because we want to have flexibility over it.
So why do we have root.html.heex?
The reason we moved the app layout to a component is because you can declare your own attributes and slots and we wanted to make it clear you should invoke it. You can’t do any of that with root layouts, so we kept them distinct to avoid confusion. Leading someone to think they should call `Layout.root` would most likely lead to disaster. 
TL;DR: the `app` and `root` layouts are defined differently as to signal users you are supposed to invoke the former but not the latter. That’s it.