docs: def _on_iteration(self, *args, **kwargs) -> None:
          """
          Called at each iteration.
  
          This function does time measurements, updates timing in the monitoring context and calls
          all monitoring tasks.
          """
  
          # Update timing and the iteration number in the monitoring context.
          current_timestamp = get_hr_time()
          self._context.optimisation_time += current_timestamp - self._last_timestamp
          self._context.total_time = current_timestamp - self._start_timestamp
          self._context.optimiser_updated = False
          if not self._context.optimisation_finished:
              self._context.iteration_no += 1
  
          # Call all monitoring functions
          for func in self._monitor_tasks:
              func(self._context, *args, **kwargs)
  
          # Remember the time when the control is returned back to the optimiser, so that the next
          # optimisation step can be accurately timed.
          self._last_timestamp = get_hr_time()