VHDL Concurrent statement comparison
There's a lot of technical details to simulation and instantiation. But I'd like to avoid the algebraic approaches and just focus on the visual aspects for a moment. It may help. (You've avoided variables, but I may decide to address them for a moment below.)
It's probably better if you think of a signal as the same thing as a named wire. So when you write the following within a begin..end block:
A1 &lt;= ((NOT L) AND (NOT M) AND N);
A2 &lt;= L and M;
F3 &lt;= A1 or A2;

All it is doing is the following:



simulate this circuit &ndash; Schematic created using CircuitLab
Note that the order of the statements don't matter. They could be arranged in any permutation you wanted. The same schematic results from those three statements, regardless of order.
Your signal names are just wires with names. That's all. The only difference between the above and what results from:
F3 &lt;= ((NOT L) AND (NOT M) AND N) or (L and M);

is:



simulate this circuit
In other words, two named wires are no longer named. That's all that happens. Since naming is a matter of convenience for humans, not for circuits, it makes no difference in the combinatorial result.
Now, there is a difference with VHDL variables. If you are familiar with C, it's perhaps better to see a variable as if it were the equivalent of a C #define and not as a physical wire in a schematic.
For example, if A1 and A2 were variables instead of signals, then:
A1 := ((NOT L) AND (NOT M) AND N);
A2 := L and M;
F3 &lt;= A1 or A2;

Would produce the same logic as in the second schematic above, except perhaps the following might be a better way of seeing it:



simulate this circuit
No wires are really named A1 or A2. Instead, the expressions for A1 and A2 were, in effect, inserted into the wire-assignment for F3. (You could still label those wires, mentally. But it's better to imagine they aren't named at all, but instead just used to replace the symbols in the final line where the wire F3 is assigned.)
There are some subtle and not-so-subtle results from this difference.
In VHDL gate-level logic, you can add an after clause to a signal assignment. But you cannot do that with a variable. That's because a variable isn't a wire representing the output of some logic. It really is more like the C language's #define.
So you can write:
A1 &lt;= ((NOT L) AND (NOT M) AND N) after 3 ns;
A2 &lt;= L and M after 1 ns;
F3 &lt;= A1 or A2 after 2 ns;

And this will affect simulation (but not instantiation.)
But, if A1 and A2 were variables, you cannot write:
A1 := ((NOT L) AND (NOT M) AND N) after 3 ns;    -- error!
A2 := L and M after 1 ns;                        -- error!
F3 &lt;= A1 or A2 after 2 ns;

Variables cannot have delays like that. The above would be an error. This is because the variables replace their mnemonics found in wire assignments (the &lt;= lines.) Variables are not wires. (Besides, the very idea of subexpressions with after clauses together with a final after clause on that wire assignment line would be quite confusing!)
Where all this actually gets interesting is in sequential logic (RTL) where you are indicating sensitivity to a std_logic signal's clock edge. Then the differences in variables and signal wires becomes far more interesting.
Assuming A1 and A2 are variables:
if rising_edge(CLK) then
    A1 := ((NOT L) AND (NOT M) AND N);
    A2 := L and M;
    F3 &lt;= A1 or A2;
end if;

You get this (where only F3 depends on the rising edge of CLK (std_logic type), as A1 and A2 are more like &quot;macros&quot; representing some logic but not actual wires):



simulate this circuit
A variable represents a block of logic and not a wire. It is meaningless to imagine that the block is sensitive to an edge of CLK. Only signal wires can be. When a wire is placed within an if..end that depends upon a rising or falling edge of some other std_logic wire, this infers an FF. As a variable isn't a wire, an FF cannot be inferred for a variable.
That is very much different from the following case where A1 and A2 are signals/wires (which do depend upon the rising edge of CLK):
if rising_edge(CLK) then
    A1 &lt;= ((NOT L) AND (NOT M) AND N);
    A2 &lt;= L and M;
    F3 &lt;= A1 or A2;
end if;

When you instead get:



simulate this circuit
Hopefully, that helps a little.