The resulting batch script is built by using string concatenation.
commands = 'BEGIN\n'
commands += cmd1
commands += cmd2
...
commands += cmdN
g.client.batch(commands)
The larger the entire script is (i.e. the commands string) the longer takes each concatenation operation (because of the underlying memory reallocation and copying).
A better approach is to use a list of strings and join it when committing.
commands = ['BEGIN']
commands.append(cmd1)
commands.append(cmd2)
...
commands.append(cmdN)
g.client.batch('\n'.join(commands)
By implementing the above solution, I was able to improve the performance with large batches by magnitudes.