I’m also confusing about the structure of doing trainer.add_event_handler() vs. the decorator of
@trainer.on(Events.EPOCH_COMPLETED(every=1)).

Normally and the intention is that both should be the same and provide the same functionnality. If it is not the case, it is a bug.
You can also pass variable using the decorator:
from ignite.engine import Engine, Events

trainer = Engine(lambda e, b: None)


@trainer.on(Events.ITERATION_COMPLETED, [0, 1, 2])
def print_my_data(_mydata):
    print("print_my_data : ", _mydata)
    
trainer.run([0])