optimize fail msg handling

No need to create all these fail msg strings if the assert passes.
This moves the custom "what failed" message definition to a block.
The block is only yielded to if the assertion fails.

This also reworks the processing of fail messages to not work in
Procs but instead just take arbitrary string args and join them with
new lines.

The added overhead of creating a block for every what failed message
should be negated by removing the overhead of creating a proc for
processing every fail message that we were already doing.