Is GML fast enough to index a image into a array of tiled pixels and then swap the colors out during run time?
Nope, that's something for a shader. With GML you would have to use draw_get_pixel to read the values, which is terribly slow. If you were trying to do this as a screen effect you'd be talking -900 FPS
I don't think you could get an array of pixels using a shader. I think it is possible in HLSL11 for shaders to return data, but I doubt GML supports that ability. If you wanted to work with palettes in a shader, I think I'd send the shader a greyscale sprite, with the amount of lightness indicating what colour to use, and then tell it to look along a second image that contained all the colours - then you could palette-swap by swapping the second image for a different image. But it would still be fiddly and unpleasant to use.
There is another way to get the values for the image.
(Unfortunately, it only works in Windows and PS4, according to the manual.) I haven't tried it, but it will always depend on size - if you're just doing a color-swap for a small sprite, I expect this will be fast enough for real time. Draw image to a surface (as small as possible, since the size of the surface will affect the speed of the operation), then use buffer_get_surface to write the data from the surface to the buffer. The size of the buffer should be the surface's width*height*4, and every 4 bytes in the buffer should contain red,blue,green and alpha bytes for the pixel. By reading 4 bytes at a time as a uint32 (the buffer functions are the only GML functions that let you create uint32 values, I think, all GML values are floats by default, so you may need to use a temporary buffer to create any uint32 variables you want to use) you can get the colour of any pixel, and swap it for a different value if you wish. Having done any operations you want to on the color data in the buffer, you can write it back to the surface with buffer_set_surface.
As for your wave effect, wipe effect and pixel fade, those all could be done with shaders, though I expect just using draw_surface_part or set_color would be fast enough. For the wave effect, for example, just draw each 1-pixel high line of the screen separately, moving them back and forth in a wave. It won't be as efficient as a shader, but simpler, and that'll be the way the gameboy did it - and if a gameboy did it without any graphics acceleration then surely a modern PC can too. (Indeed, I did similar effects back on my old 16Mb Pentium-120 back when we had no graphics cards or shaders.)