Out of curiosity I implemented this "cache the result of draw() as a Sprite" scheme. The short of it is: it makes the code messy, fragile, with likely no meaningful performance gain.
The long version: after draw()-ing to the canvas (but still inside of draw()) I use ctx.getImageData() to grab the area of the canvas that I drew onto (while respecting Engine.pixelRatio). This ImageData I then render to another (invisible) canvas using putImageData(). I then invoke toDataURL() on the invisible canvas and pass the result to Texture's constructor. Invoking asSprite() on the Texture object yields a sprite. Voilà, (part of) the draw()ing turned into a Sprite.
You can then cache this Sprite object somewhere to later render it during update() in the right position (note: getImageData() uses top left coordinates, whereas an Actor uses the middle point) and at the right scale (because Engine.pixelRatio). I used Actor's addDrawing(cacheKey, sprite) and setDrawing(cacheKey) to store and render sprites. Obviously, update() needs to make sure it only bothers to change the sprite if the state of the Actor requires it.
Beware,though: when you override draw(), no call to update() will happen. They are mutually exclusive. If you're hoping to prevent an expensive draw() by doing an elegant Sprite render in update(), you'll need to make sure that draw() falls back to its default behavior by calling super.draw() and return from draw() if you have a hit in your custom sprite cache and want update() to take care of rendering the sprite.
I didn't do deep performance testing, but just eyeballing the browser's CPU usage, it made no meaningful difference. All in all, it's a no-good optimization. Learned a lot, though.