Answering my own question here in case anyone ever runs into the same issue.
The argument num_beams used by .generate() defaults to the value specified in the model’s config file (e.g. config.json). If this value is > 1, decoding will be performed with beam search (either regular or sampled).
So, the simple fix is to explicitly set num_beams=1 in the call to .generate(), e.g.:
output = model.generate(input_ids=inputs['input_ids'], attention_mask=inputs['attention_mask'], use_cache=True, max_length=max_length, pad_token_id=tokenizer.pad_token_id, decoder_start_token_id=tokenizer.pad_token_id, do_sample=True, top_k=0, num_beams=1, num_return_sequences=num_return_sequences, return_dict_in_generate=True)

print(type(outputs)) # ==> transformers.generation_utils.SampleEncoderDecoderOutput

Lesson of the day: keep calm and read the docstrings carefully! transformers/generation_utils.py at 91ff480e2693f36b11aaebc4e9cc79e4e3c049da · huggingface/transformers · GitHub 2