You say you have debt owners and you have to repay quite a few. Ideally, this uses a withdrawal pattern and you avoid iteration altogether. I realize this is not always feasible. In cases like airdrops there can be a strong desire to use a use "push" process to send a batch of transactions. I'll assume there is a good reason.
On the contract side
You can iterate over a list of distributions and log success/fail as you go. You will want to use
.send() so the whole process isn't held up by a single failed transaction. Since the sender has control of batch size, this is a case where you can use arrays for input and unbounded iteration. The sender can determine the optimal batch size. This is more gas-efficient than a purist approach insisting on one
.send() per signed transaction.
The client is likely a server, but could be a browser, etc. Let's assume server. I mentioned earlier that the contract should emit success/fail while it thunders ahead undeterred by send failures. What to do with the send failures is a client-side concern, perhaps retry, perhaps a withdrawal pattern, perhaps give up. I merely assume the server needs to be informed.
On the sender side
A less obvious concern is nonce management. Whether batches or single transactions, to get significant volume through, the server and blockchain will probably use an asynchronous interface. That is, the server won't wait for confirmation before sending the next transaction. Consider deliberate throttling.
The server won't know the transactions were successful until sufficient confirmations are received. So there's the success/fail event and waiting for (10?) confirmations before declaring victory. I have found it's also important to have the ability to recall transactions that are overdue (maybe the gas was too low). You need to "recall" to have positive confirmation that the transaction is indeed failed and not merely indeterminant. This, so the server can confidently try again and be certain the end result won't be two payments to the same recipient.
In practice, this leads to a server that is tracking its pending transactions and their nonce perchance to emit a cancellation with the same nonce.
With so many pending transactions floating about, the client-side (say, geth) nonce is not reliable. Same for Infura. Pending transactions are subjective from the node perspective and a miss by even one will result in various errors and jam up the process.
In the end, you probably set up a singleton nonce counter of your own based on the idea that the sender is most qualified to know what was sent. More on the technical issues of infrastructure for this over here: Concurrency patterns for account nonce
Hope it helps.