In reply to 100rabhh:
If you look at the definition of the macro uvm_do_on_with (uvm_1.1d) in the file uvm_sequence_defines.h you will notice that it calls another macro
uvm_do_on_pri_with which in turn expands to
start_item(), randomize() and finish_item() if a sequence_item is passed into the macro. If a sequence is passed to the macro, then it expands to seq.start(sequencer).
So really it is matter of personal preference. The macros are certainly convenient if you would like to do less coding. However you will not be able to set a breakpoint and debug the underlying code of the macro (in case something goes wrong). So if you feel that you debuggability is important in your situation then you may want to consider calling the API functions directly.