From pygame docs pygame.display.flip():
"if your display mode is using the flags pygame.HWSURFACE and
pygame.DOUBLEBUF, this will wait for a vertical retrace and swap the
surfaces."
This means that surfaces and sprites are drawn, ie. copied or blited, to another area of video memory that is not currently being displayed. At the vertical retrace, ie. when the previous frame was fully drawn, and the next one did not started to be drawn yet, the pointer to the address of the area of video memory to display next is changed to the area where sprites were drawn, the double buffer. This has a swap screen effect and is much faster than copying the whole image.
This also avoids screen tearing, ie. part of the previous frame to be drawn with part of the next frame, since the swapping to the double buffer is made when the hardware is not updating the display.
Some times, when using a fixed surface as background, pygame.display.update() can be faster, since only the areas of the sprites that moved between frames are updated.