I am not a compiler expert but this notion that there are optimisations to be had in the more expressive higher-level compiler IR and then delaying the emitting of machine code rings true. I would be grateful were anyone able to direct me to some papers etc on the subject.
Relocations are instructions executed by the linker (or loader). Write the address of this symbol to this offset from the start of the data section, stuff like that. Relaxations cover things like a branch target turned out to be closer than it might have been so change the instruction sequence to a smaller/faster one.
So if you don't eagerly convert to machine code, you don't need the link time relocation data, so the assembler and linker don't need the code to deal with it.
Of course if you stay in a friendly IR you can also do optimisations easily at link time, so most articles on this approach call it 'link time optimisation'.
The assembler is often spliced into the back end of the compiler to avoid the round trip through text on the way to machine code.
My conviction is that lowering to machine code in pieces then stitching them together is no longer necessary or advisable. Emit files containing some richer format - most obviously a compiler IR - and combine those before lowering the single blob to machine code.