In botorch/gen.py, gen_candidates_torch evaluates loss / the acquisition function twice per iteration: Once at line 206 for reporting / book keeping purposes, and once at line 218 for the optimizer iteration.
In line 218, bayes_optimizer.step(closure) has a return value of loss which can be used for reporting / book keeping purposes without the need to evaluate it again at line 206. This would half the number of acquisition function evaluations needed.